/**
 * @description 运动 controller
 */
const dayjs = require('dayjs')
const _ = require('lodash')
const { getRandomInt } = require('../utils/math')
const {
  createExercise,
  getExerciseData,
} = require('../services/exercise')
const { SuccessModel, ErrorModel } = require('../model/ResModel')
const {
  createExerciseFailInfo,
  getExerciseDataFailInfo,
} = require('../model/ErrorInfo')
const BADGES = require('../constants/badge');

const DATE_FORMAT = 'YYYY-MM-DD'

// 保存运动数据
async function saveExercise(ctx, exerciseData) {
  const toSave = {}
  if (!_.isUndefined(exerciseData.type)) { toSave.type = exerciseData.type }
  if (!_.isUndefined(exerciseData.duration)) { toSave.duration = exerciseData.duration }
  if (!_.isUndefined(exerciseData.meter)) { toSave.meter = exerciseData.meter }
  if (!_.isUndefined(exerciseData.calorie)) { toSave.calorie = exerciseData.calorie }

  const { id: userId } = ctx.state.tokenPayload;
  toSave.userId = Number(userId);

  try {
    const exerciseInfo = await createExercise(toSave)
    return new SuccessModel(exerciseInfo)
  } catch(ex) {
    console.error(ex.message, ex.stack)
    return new ErrorModel(createExerciseFailInfo)
  }
}

// 获取运动数据
async function getExercise(ctx) {
  const { id } = ctx.state.tokenPayload

  let exerciseData = await getExerciseData(id) // 如果当前用户无运动数据，得到 []

  // exerciseData 的数据结构：
  // [{ id: 1, type: 2, duration: 18, meter: null, calorie: 176, createdAt: 2021-11-30T01:29:12.000Z }, ...]
  if (exerciseData === null) { return new ErrorModel(getExerciseDataFailInfo) }

  // 格式化处理 exerciseData，便于后续计算
  exerciseData = exerciseData.map((exercise) => {
    const { duration, meter, calorie, createdAt } = exercise;
    return {
      ...exercise,
      duration: duration === null ? 0 : duration,
      meter: meter === null ? 0 : meter,
      calorie: calorie === null ? 0 : calorie,
      createdAt: dayjs(createdAt).format(DATE_FORMAT)
    }
  })

  // 构造近七日运动数据，如果当日有数据，就用当日真实数据，否则随机生成
  const last7Date = dayjs().subtract(6, 'day').format(DATE_FORMAT); // 7天前的日期，今天也包含在这 7 天中
  const today = dayjs();
  let nextDate = last7Date; // 用于遍历的日期
  let sum7Duration = 0; // 近七日运动总秒数
  let sum7Meter = 0; // 近七日运动总米数
  let sum7Calorie = 0; // 近七日运动总卡路里
  const days = []; // 近七日的每日运动数据结果数组
  // 从7天前遍历至今天
  while(dayjs(nextDate).diff(today, 'hour') <= 0) {
    // 从 exerciseData 中过滤出当前遍历日期数据
    const nextArr = exerciseData.filter(item => item.createdAt === nextDate);

    if (nextArr.length === 0) {
      // 无当前遍历日数据，构造随机新数据
      const day = {
        date: nextDate, // 日期
        count: getRandomInt(0, 10), // 运动次数
        sumDuration: 0, // 当日总运动时长
        sumMeter: 0, // 当日总米数
        sumCalorie: 0, // 当日总卡路里
        exerciseData: [{
          type: 0, // 跑步
          duration: getRandomInt(0, 1800), // 0~30 min
          meter: getRandomInt(0, 2000), // 0~2000 米
          calorie: getRandomInt(0, 500), // 0~500 卡
        }, {
          type: 1, // 骑行
          duration: getRandomInt(0, 1800), // 0~30 min
          meter: getRandomInt(0, 5000), // 0~5000 米
          calorie: getRandomInt(0, 900), // 0~900 卡
        }, {
          type: 2, // 课程训练
          duration: getRandomInt(0, 1200), // 0~20 min
          meter: getRandomInt(0, 1000), // 0~1000 米
          calorie: getRandomInt(0, 400), // 0~400 卡
        }]
      }
      // 统计总值
      day.exerciseData.forEach(data => {
        day.sumDuration += data.duration
        day.sumMeter += data.meter
        day.sumCalorie += data.calorie
      })
      days.push(day);
      sum7Duration += day.sumDuration
      sum7Meter += day.sumMeter
      sum7Calorie += day.sumCalorie
    } else {
      // 有当前遍历日数据，整合数据
      const realDay = {
        date: nextDate, // 日期
        count: nextArr.length, // 运动次数
        sumDuration: 0, // 当日总运动时长
        sumMeter: 0, // 当日总米数
        sumCalorie: 0, // 当日总卡路里
        exerciseData: [{
          type: 0, // 跑步
          duration: 0,
          meter: 0,
          calorie: 0,
        }, {
          type: 1, // 骑行
          duration: 0,
          meter: 0,
          calorie: 0,
        }, {
          type: 2, // 课程训练
          duration: 0,
          meter: 0,
          calorie: 0,
        }]
      }
      // 将 nextArr 的数据统计进 realDay 中
      nextArr.forEach(item => {
        const { type, duration, meter, calorie } = item
        realDay.exerciseData[type].duration += duration
        realDay.exerciseData[type].meter += meter
        realDay.exerciseData[type].calorie += calorie
        realDay.sumDuration += duration
        realDay.sumMeter += meter
        realDay.sumCalorie += calorie
      })
      days.push(realDay);
      sum7Duration += realDay.sumDuration
      sum7Meter += realDay.sumMeter
      sum7Calorie += realDay.sumCalorie
    }

    // 日期加 1 天
    nextDate = dayjs(nextDate).add(1, 'day').format(DATE_FORMAT)
  }

  return new SuccessModel({
    sum7Duration,
    sum7Meter,
    sum7Calorie,
    days,
  })
}

// 获取个人徽章
async function getBadge(ctx) {
  const dist = [];

  BADGES.forEach(badgeData => {
    const randomNum = getRandomInt(1, 10);
    if (randomNum > 5) {
      const { id, name, level } = badgeData
      const randomLevel = getRandomInt(0, 2);
      const detail = level[randomLevel];
      const month = getRandomInt(1, 12);
      const day = getRandomInt(1, 30);
      dist.push({
        id,
        name,
        detail,
        date: `2021-${month}-${day}`
      })
    }
  })

  return new SuccessModel(dist);
}

module.exports = {
  saveExercise,
  getExercise,
  getBadge,
}
